///PHILOTES Source Code.  (C)2012 PhiloLabs
#pragma once

#include "ExtrasPrerequisites.h "

#include "OgreSceneNode.h"
#include "OgreIteratorWrappers.h"
#include "math/matrix4.h "

namespace Extras {

	class _PhiloExtrasExport Overlay : public MemAlloc_SceneObj
    {

    public:
              typedef list<OverlayContainer*>::type OverlayContainerList;
    protected:
        Ogre::String mName;
        /// Internal root node, used as parent for 3D objects
        SceneNode* mRootNode;
        // 2D elements
        // OverlayContainers, linked list for easy sorting by zorder later
        // Not a map because sort can be saved since changes infrequent (unlike render queue)
        OverlayContainerList m2DElements;

        // Degrees of rotation around center
        Radian mRotate;
        // Scroll values, offsets
        Real mScrollX, mScrollY;
        // Scale values
        Real mScaleX, mScaleY;

        mutable Matrix4 mTransform;
        mutable bool mTransformOutOfDate;
        bool mTransformUpdated;
        ulong mZOrder;
        bool mVisible;
		bool mInitialised;
		Ogre::String mOrigin;
        
        void updateTransform(void) const;
		
		void initialise(void);
		
		void assignZOrders(void);

    public:
        /// Constructor: do not call direct, use OverlayManager::create
        Overlay(const Ogre::String& name);
        virtual ~Overlay();


	    OverlayContainer* getChild(const Ogre::String& name);

        
        const Ogre::String& getName(void) const;
        
        void setZOrder(ushort zorder);
        
        ushort getZOrder(void) const;

        
        bool isVisible(void) const;

		
		bool isInitialised(void) const { return mInitialised; }

		
        void show(void);

        
        void hide(void);

        
        void add2D(OverlayContainer* cont);


        
        void remove2D(OverlayContainer* cont);

        
        void add3D(SceneNode* node);

        
        void remove3D(SceneNode* node);

        
        void clear();

        
        void setScroll(Real x, Real y);

        
        Real getScrollX(void) const;

        
        Real getScrollY(void) const;

        
        void scroll(Real xoff, Real yoff);

        
        void setRotate(const Radian& angle);

        
        const Radian &getRotate(void) const { return mRotate; }

        
        void rotate(const Radian& angle);

        
        void setScale(Real x, Real y);

        
        Real getScaleX(void) const;

        
        Real getScaleY(void) const;

        
        void _getWorldTransforms(Matrix4* xform) const;

        
        void _findVisibleObjects(Camera* cam, RenderQueue* queue);

        
		virtual OverlayElement* findElementAt(Real x, Real y);

        
        typedef VectorIterator<OverlayContainerList> Overlay2DElementsIterator ;
        Overlay2DElementsIterator get2DElementsIterator ()
        {
            return Overlay2DElementsIterator (m2DElements.begin(), m2DElements.end());
        }
		
		const Ogre::String& getOrigin(void) const { return mOrigin; }
		/// Notify this overlay of it's origin
		void _notifyOrigin(const Ogre::String& origin) { mOrigin = origin; }


    };
	
}

